﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.Timers;
using Reborn_WorldServer;

namespace Reborn_Server.App1AppHandler
{
    public class Spell_Burn : AreaSpell
    {
        public Spell_Burn() 
        {
            DurationLow = 5;
            DurationHigh = 5;
        }

        private int BaseIceDamageLow = 50;
        private int BaseIceDamageHigh = 65;

        private int BaseFireDamageLow = 75;
        private int BaseFireDamageHigh = 100;

        public int DamageLow = 50;
        public int DamageHigh = 70;

        public void CreatureCast(SpellIcon _spellIcon, CreatureBase myCreatureBase, int CastLevel, int MapX, int MapY)
        {
            List<MapItem> MapItemsWithin12;
            base.InitializeInstantCast(myCreatureBase, CastLevel, _spellIcon, MapX, MapY, out MapItemsWithin12);

            myCreatureBase.Mana = myCreatureBase.Mana - _spellIcon.ManaCost;
            myCreatureBase.WarmSpell = null;

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(CastLevel, DamageLow, myCreatureBase.IntelligenceTotal);
            DamageHigh = SkillManager.AdjustForCombat(CastLevel, DamageHigh, myCreatureBase.IntelligenceTotal);

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        bool isIndirect = false;
        //Overload used for pets or when effects trigger this. myCreature is the pet or creature that spawns this spell, Source values are the values of the origional caster
        public void IndirectPositionCast(SpellIcon _spellIcon, CreatureBase castingCreatureBase, int targetMapX, int targetMapY, int castLevel, int SourceCastInt, int SourceCastWis, int SourceCharID)
        {
            List<MapItem> MapItemsWithin12;
            base.InitializeIndirectInstantCast(castingCreatureBase, castLevel, _spellIcon, targetMapX, targetMapY, SourceCharID, out MapItemsWithin12);

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(castLevel, DamageLow, SourceCastInt);
            DamageHigh = SkillManager.AdjustForCombat(castLevel, DamageHigh, SourceCastInt);

            CastingCreatureInt = SourceCastInt;
            CastingCreatureWis = SourceCastWis;
            CastingCreatureLevel = castLevel;

            isIndirect = true;
            MainCast(castingCreatureBase, targetMapX, targetMapY, MapItemsWithin12);
        }
        public void PositionCast(SpellIcon _spellIcon, CreatureBase myCreatureBase, int CastLevel, int MapX, int MapY)
        {
            List<MapItem> MapItemsWithin12;
            base.InitializeInstantCast(myCreatureBase, CastLevel, _spellIcon, MapX, MapY, out MapItemsWithin12);

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(CastLevel, DamageLow, myCreatureBase.IntelligenceTotal);
            DamageHigh = SkillManager.AdjustForCombat(CastLevel, DamageHigh, myCreatureBase.IntelligenceTotal);

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        private void MainCast(CreatureBase myCreatureBase, int MapX, int MapY, List<MapItem> MapItemsWithin12)
        {
            //Set Duration & Damage Per Character Stats
            DurationLow = 5;
            DurationHigh = 5;

            CastMapX = MapX;
            CastMapY = MapY;

            List<Character> CharactersWithinUpdateRange = new List<Character>();
            foreach (MapItem mapitem in MapItemsWithin12)
            {
                foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                {
                    if (creatureBase is Character)
                        CharactersWithinUpdateRange.Add((Character)creatureBase);
                }
                //Add this spell to each mapitem in range & record mapitem for timer
                if ((mapitem.MapX == CastMapX && mapitem.MapY == CastMapY) &&
                    mapitem.Motion > 0 && mapitem.TerrainType != "Water" && mapitem.Transparent == true)
                {
                    if (spellIcon.Skill == "Fire")
                    {
                        foreach (Spell spell in mapitem.SpellLayer0)
                        {
                            if (spell.spellIcon.StackType != "" && spell.spellIcon.StackType == spellIcon.StackType)
                            {
                                mapitem.SpellLayer0.Remove(spell);
                                break;
                            }
                        }
                        mapitem.SpellLayer0.Add(this);
                    }
                    else if (spellIcon.Skill == "Ice")
                    {
                        foreach (Spell spell in mapitem.SpellLayer1)
                        {
                            if (spell.spellIcon.StackType != "" && spell.spellIcon.StackType == spellIcon.StackType)
                            {
                                mapitem.SpellLayer1.Remove(spell);
                                break;
                            }
                        }
                        mapitem.SpellLayer1.Add(this);
                    }
                    
                    MapItems.Add(mapitem);
                }
            }

            //Record all the creatures to damage first, damage them later (damaging them may remove them from the mapitem which will break our iteration)
            List<CreatureBase> creaturesToDamage = new List<CreatureBase>();
            foreach (MapItem mapitem in MapItems)
            {
                foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                {
                    if (creatureBase.HP < 1)
                        continue;

                    creaturesToDamage.Add(creatureBase);
                }
            }

            foreach (CreatureBase creatureBase in creaturesToDamage)
            {
                if (creatureBase.HP < 1)
                    continue;

                //If this is indirect, the hate goes to the source (like an exploding pet, the pet is the caster, the source is the master)
                CreatureBase attackingCreature = myCreatureBase;

                if (isIndirect)
                {
                    if (CastingCharacterID != -1)
                        attackingCreature = Managers.characterManager.getCharacter(CastingCharacterID);
                }

                //Get the creature we would give a SD flag to.
                Character characterToApplyFlag = null;

                //If the creature we're casting at is a pet, get its master
                Pet_Controller pc = creatureBase.petController;
                //Has pet controller, check if master is character
                if (pc != null && pc.MasterCreature is Character)
                    characterToApplyFlag = (Character)pc.MasterCreature;
                //No pet controller, check if target is character
                else if (pc == null && creatureBase is Character)
                    characterToApplyFlag = (Character)creatureBase;

                //If we're attacking a player, and we dont have a flag on them, give them a flag on us.
                if (attackingCreature != null &&
                    characterToApplyFlag != null &&
                    attackingCreature is Character &&
                    characterToApplyFlag != myCreatureBase &&
                    attackingCreature.hateManager.GetCreatureHateInfo(characterToApplyFlag) == null &&
                    spellIcon.Offensive == true)
                {
                    Character charToAttack = (Character)characterToApplyFlag;
                    if (charToAttack.friendsManager.hasNoSDFlag(CastingCharacterID) == false)
                    {
                        if (charToAttack.hateManager.GetCreatureHateInfo(attackingCreature) == null)
                        {
                            charToAttack.SendMessage("You have been ATTACKED by " + attackingCreature.Name + "!", "damaged");
                            charToAttack.PlaySound("Ding", charToAttack.MapX, charToAttack.MapY);

                            charToAttack.hateManager.UpdateList(attackingCreature, 0);

                            charToAttack.AddMapItem(attackingCreature.currentMapItem);
                        }
                        else
                            charToAttack.hateManager.UpdateList(attackingCreature, 0);
                    }
                }

                int dmg = Managers.GameHandler.random.Next(DamageLow, DamageHigh + 1);
                int reducedDamage = creatureBase.CalculateGetSpellDamagePerResists(dmg, this.spellIcon.Skill);
                int absorbedDamage;
                creatureBase.InflictSpellDamage(reducedDamage, CastingCharacterID, CastingCreatureGUID, spellIcon.Skill, out absorbedDamage);
                creatureBase.Update_Character();

                reducedDamage = reducedDamage - absorbedDamage;

                string targetMessageText = "";
                string casterMessageText = "";
                if (spellIcon.Skill == "Ice")
                {
                    targetMessageText = "You are freezing! (" + reducedDamage.ToString() + ")";
                    casterMessageText = "You freeze " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                }
                else if (spellIcon.Skill == "Fire")
                {
                    targetMessageText = "You are burning! (" + reducedDamage.ToString() + ")";
                    casterMessageText = "You burn " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                }

                if (absorbedDamage != 0 && targetMessageText != "")
                    targetMessageText = targetMessageText + " ABSORBED " + absorbedDamage.ToString();
                if (absorbedDamage != 0 && casterMessageText != "")
                    casterMessageText = casterMessageText + " ABSORBED " + absorbedDamage.ToString();

                if (targetMessageText != "")
                    creatureBase.SendMessage(targetMessageText, "spelldamaged");
                if (casterMessageText != "")
                    Managers.GameHandler.TrySendMessage(CastingCharacterID, casterMessageText, "spelldamage");
            }

            foreach (MapItem mapitem in MapItems)
            {
                for (int x = 0; x < mapitem.CreaturesBases.Count; x++)
                {
                    CreatureBase creaturebase = (CreatureBase)mapitem.CreaturesBases[x];

                    if (creaturebase.HP < 1)
                    {
                        if (!(creaturebase is Character))
                        {
                            mapitem.CreaturesBases.RemoveAt(x);
                            x--;
                        }
                    }
                }
            }

            if (MapItems.Count > 0)
            {
                foreach (Character character in CharactersWithinUpdateRange)
                {
                    character.AddMapItems(MapItems, false);

                    if (spellIcon.Skill == "Fire")
                        character.PlaySound("FireBall", CastMapX, CastMapY);
                }
            }

            //Start Spell Timer
            spellTimer.Start();
        }



        public void Cast(CreatureBase myCreatureBase, int CastLevel, List<string> MoveList)
        {
            List<MapItem> MapItemsWithin12;
            if (base.InitializeCast(myCreatureBase, CastLevel, MoveList, out MapItemsWithin12) == false)
                return;

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(CastLevel, DamageLow, myCreatureBase.IntelligenceTotal);
            DamageHigh = SkillManager.AdjustForCombat(CastLevel, DamageHigh, myCreatureBase.IntelligenceTotal);

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        protected override void SpellTimer_Expired(object source, ElapsedEventArgs e)
        {
            TimerCounter = TimerCounter + 1;

            //Get MapLock
            LockItem MapLock = Managers.GameHandler.GetLockItem(MapID, Instance);

            //Lock MapLock
            lock (MapLock.LockObj)
            {
                Map CurrentMap = Managers.GameHandler.GetMap(MapID, Instance);

                //Stop Running if no mapitems
                bool FoundItem = false;
                foreach (MapItem mapitem in MapItems)
                {
                    if (mapitem.SpellLayer0.Contains(this) || mapitem.SpellLayer1.Contains(this))
                    {
                        FoundItem = true;
                        break;
                    }
                }
                if (FoundItem == false)
                    return;

                List<MapItem> MapItemsToUpdate = new List<MapItem>();

                foreach (MapItem mapitem in MapItems)
                {
                    bool foundSpell = false;
                    if (spellIcon.Skill == "Fire" && mapitem.SpellLayer0.Contains(this))
                        foundSpell = true;
                    else if (spellIcon.Skill == "Ice" && mapitem.SpellLayer1.Contains(this))
                        foundSpell = true;

                    if (foundSpell == false)
                        continue;

                    if (TimerCounter >= DurationLow)
                    {
                        if (mapitem.MapX != CastMapX || mapitem.MapY != CastMapY)
                        {
                            int RemoveSpell = Managers.GameHandler.random.Next(-1, DurationHigh - TimerCounter);
                            if (RemoveSpell == -1)
                            {
                                if (spellIcon.Skill == "Fire")
                                    mapitem.SpellLayer0.Remove(this);
                                else if (spellIcon.Skill == "Ice")
                                    mapitem.SpellLayer1.Remove(this);

                                MapItemsToUpdate.Add(mapitem);
                                continue;
                            }
                        }
                        else if (TimerCounter >= DurationHigh)
                        {
                            if (spellIcon.Skill == "Fire")
                                mapitem.SpellLayer0.Remove(this);
                            else if (spellIcon.Skill == "Ice")
                                mapitem.SpellLayer1.Remove(this);

                            MapItemsToUpdate.Add(mapitem);
                            continue;
                        }
                    }
                    if (spellIcon.Skill == "Fire")
                    {
                        Corpse corpse = CurrentMap.LootMngr.GetFirstCorpse(mapitem.MapX, mapitem.MapY);
                        if (corpse != null)
                        {
                            Managers.GameHandler.Corpse_Roll(null, MapID, Instance, mapitem.MapX, mapitem.MapY, corpse.GameUID);
                        }
                        else
                        {
                            CorpseCharacter charCorpse = CurrentMap.LootMngr.GetFirstCharacterCorpse(mapitem.MapX, mapitem.MapY);
                            if (charCorpse != null)
                            {
                                Managers.GameHandler.Corpse_Roll(null, MapID, Instance, mapitem.MapX, mapitem.MapY, charCorpse.GameUID);
                                Managers.GameHandler.Resurrect(charCorpse.MyCharacter);
                            }
                        }
                    }
                    MapItemsToUpdate.Add(mapitem);
                }

                List<Character> CharsToUpdate = new List<Character>();
                //Send Updated Hexes to all characters within 8 of any hex effected
                foreach (MapItem mapitem in CurrentMap.MapItems)
                {
                    foreach (MapItem mitem in MapItems)
                    {
                        if (mapitem.MapX - mitem.MapX >= -12 && mapitem.MapX - mitem.MapX <= 12 && mapitem.MapY - mitem.MapY >= -12 && mapitem.MapY - mitem.MapY <= 12)
                        {
                            foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                            {
                                if (creatureBase is Character)
                                    CharsToUpdate.Add((Character)creatureBase);
                            }
                            break;
                        }
                    }
                }

                List<CreatureBase> creaturesToDamage = new List<CreatureBase>();
                foreach (MapItem mapitem in MapItemsToUpdate)
                {
                    foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                    {
                        if (creatureBase.HP > 1)
                            creaturesToDamage.Add(creatureBase);
                    }
                }

                foreach (CreatureBase creatureBase in creaturesToDamage)
                {
                    int dmg = Managers.GameHandler.random.Next(DamageLow, DamageHigh + 1);
                    int reducedDamage = creatureBase.CalculateGetSpellDamagePerResists(dmg, this.spellIcon.Skill);
                    int absorbedDamage;
                    creatureBase.InflictSpellDamage(reducedDamage, CastingCharacterID, CastingCreatureGUID, spellIcon.Skill, out absorbedDamage);
                    creatureBase.Update_Character();

                    reducedDamage = reducedDamage - absorbedDamage;

                    string targetMessageText = "";
                    string casterMessageText = "";
                    if (spellIcon.Skill == "Ice")
                    {
                        targetMessageText = "You are freezing! (" + reducedDamage.ToString() + ")";
                        casterMessageText = "You freeze " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                    }
                    else if (spellIcon.Skill == "Fire")
                    {
                        targetMessageText = "You are burning! (" + reducedDamage.ToString() + ")";
                        casterMessageText = "You burn " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                    }

                    if (absorbedDamage != 0 && targetMessageText != "")
                        targetMessageText = targetMessageText + " ABSORBED " + absorbedDamage.ToString();
                    if (absorbedDamage != 0 && casterMessageText != "")
                        casterMessageText = casterMessageText + " ABSORBED " + absorbedDamage.ToString();

                    if (targetMessageText != "")
                        creatureBase.SendMessage(targetMessageText, "spelldamaged");
                    if (casterMessageText != "")
                        Managers.GameHandler.TrySendMessage(CastingCharacterID, casterMessageText, "spelldamage");
                }

                foreach (MapItem mapitem in MapItemsToUpdate)
                {
                    //Remove Creatures
                    bool Complete = false;
                    while (Complete == false)
                    {
                        int count = 0;
                        if (mapitem.CreaturesBases.Count == 0)
                            Complete = true;
                        foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                        {
                            count = count + 1;
                            if (creatureBase.HP < 1 && !(creatureBase is Character))
                            {
                                mapitem.CreaturesBases.Remove(creatureBase);
                                break;
                            }
                            if (count == mapitem.CreaturesBases.Count)
                            {
                                Complete = true;
                            }
                        }
                    }
                }
                foreach (Character character in CharsToUpdate)
                {
                    character.AddMapItems(MapItemsToUpdate, false);
                }
            
            }//End Lock

            spellTimer.Start();
        }
    }
}
